Using MomentJS to manage dates and times easily


Getting a new project is always an exciting part of being a Software Engineer in OnePageCRM, and on this occasion, when I heard the brief on our latest feature: Next Action Quick Date Select and Next Action Quick Edit, I was excited, as it meant I was going to check out a new library. With this update, users can easily update the date of a Next Action right from the Action Stream from a predefined list of options for example: today, tomorrow, etc. It’s also possible to edit the Next Action text right from the Contact view. This saves the user time and allows them to organize their day better.

quick select

After doing some initial research, I realized that the best way to implement this feature was to use a lightweight and powerful library called MomentJS. In this post, I want to highlight some of the great features of MomentJS and my experience working with it.

First, you need to install the library using a package management tool. I used npm:

npm install moment


Don’t forget to include it:

var moment = require('moment')


Simply call moment in your code:

moment() # -> Moment {...}


It returns a MomentJS object that points to the current date and time. This call is equal to:

moment(new Date()) # -> Moment {...}


Now, you can consume it as per your needs. For example, you want to display date and time in some user preferred format, then call the format method:

moment().format("MM/DD/YYYY") # -> "02/06/2020"
moment().format("HH:mm") # -> "16:26"


The method format is widely used to display dates for users in an appropriate way. It can be used for debugging purposes as well. For example, when you need to quickly convert a MomentJS object to string and check the date or time value, just call format without any parameter:

moment().format() # -> "2020-02-12T18:09:06+03:00"


Local formats are also useful, and quite easy to output (but remember that the date and time will be shown in local time!):

moment().format('L')  # -> "02/07/2020" month/day/year
moment().format('LL') # -> "February 7, 2020"
moment().format('LT') # -> "7:37 PM"


Also the calendar method can be helpful for a quick check or manipulation:

moment().calendar() # -> "Today at 5:21 PM"
moment().add(1, 'days').calendar() # -> "Tomorrow at 5:22 PM"
moment('25-01-1990', 'DD-MM-YYYY').calendar() # -> "01/25/1990" month/day/year


To quickly get Unix time, pass ‘X’ as the format parameter, or use the unix method:

var a = moment()
a.format('X') # -> "1581094632" # string
a.unix()      # -> 1581094632   # same but returned as a number
a.format('x') # -> "1581094632798" # with milliseconds


To understand what is going on with offset, the utcOffset method is helpful. Use it to set the value as well:

moment().utcOffset() # -> 180 # which means +3 hours
moment("2020-02-07T19:49:37+03:00").format('LT') # -> "7:49 PM"
moment("2020-02-07T19:49:37+03:00").utcOffset(0).format('LT') # -> "4:49 PM"


If you already have a date as a string, from an API for example, it’s easy to convert it to a MomentJS object:

moment("01/31/2020", "MM/DD/YYYY") # -> Moment {...}


The second parameter is the date format. Interestingly, when you are not sure about the exact format, you can provide multiple formats. MomentJS will determine which format to use by itself:

moment("06-02-2020", ["MM-DD-YYYY", "YYYY-MM-DD"]) # -> "MM-DD-YYYY" will be chosen


When parsing date-times, we are not always sure about the format of the information. I found that we can easily address these concerns by checking with the isValid method. For example:

moment("01/31/2020", "MM/DD/YYYY").isValid() # -> true
moment("", "MM/DD/YYYY").isValid() # -> false
moment("hello", "MM/DD/YYYY").isValid() # -> false


When you want to change a date, the methods add and subtract are helpful (but remember that it changes the original date). For example:

today = moment()
today.add(1, 'days').format('LL') # -> "February 13, 2020"
today.format('LL') # ->  "February 13, 2020" # same date now!!!


If you want to keep the original date unedited, use the clone method. Here is an example how to calculate Tomorrow and upcoming Friday dates:

today = moment()
day = today.isoWeekday() # -> 3 # Wednesday
tomorrow = today.clone().add(1, 'days')
friday = today.clone().add(5 - day, 'days')


Frequently, it’s more convenient to show relative time on the user’s side, instead of the full date-time format. We can use the fromNow method for this:

a = moment()
a.fromNow() # -> "a few seconds ago"
moment("10/02/2020", "DD/MM/YYYY").fromNow() # -> "4 days ago"


If you want, you can implement your own logic using the diff method. For example:

date = moment("13/02/2020", "DD/MM/YYYY")
minutesAgo = moment().diff(date,'minutes')
hoursAgo = moment().diff(date,'hours')
if minutesAgo <= 60
  "#{minutesAgo} minutes ago" #-> 2 minutes ago
else
  "#{hoursAgo} hours ago"     #-> 5 hours ago


Methods like isBefore and isSame can help here also:

moment('2020-01-01').isBefore('2020-01-02') # -> true
moment('2020-01-01').isBefore('2020-01-02', 'year') # -> false #check only year
moment('2020-01-01').isSame('2020-01-01') # -> true
moment('2020-01-01').isSame('2020-08-01', 'year') # -> true #check only year

(Note: instead of year, you can pass other units of time such as month, day, hour, minute or second).



Conclusion

MomentJS is an awesome JS library that allows you to manipulate, parse and validate dates and times easily. It simplifies the development process significantly, which means it’s a great addition to your arsenal. I’d strongly recommend you visit the official docs page, as it contains exhaustive information about the library and many usage examples.



  1. Quick start with MomentJS https://momentjs.com/
  2. MomentJS exhaustive documentation https://momentjs.com/docs/
  3. When you’re dealing with timezones https://momentjs.com/timezone/



Image references: OnePageCRM and Pexels

Author image

Victor Pukman

Software Engineer at OnePageCRM. Enjoys developing features which help people to solve real problems. Experience in Ruby and CoffeeScript. In his spare time, Victor plays music and enjoys exploring new places.